home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 076-100 / 079 / sharedlib / library.c < prev    next >
C/C++ Source or Header  |  1995-03-13  |  7KB  |  258 lines

  1. /* Library.c
  2.  *    Routines required in all shared libraries.
  3.  *    Copyright 1986 by James M Synge.
  4.  */
  5.  
  6. #include "exec/types.h"
  7. #include "exec/libraries.h"
  8. #include "ExtLibrary.h"
  9. #include "libraries/dos.h"
  10.  
  11. /* Declare the name of the library    */
  12.  
  13. char LibraryName[] = "task.library";
  14. char LibraryId[] =
  15.     "task.library V1.0 (25 May 1987)\015\012";
  16.  
  17. #define LIB_VERSION    1
  18. #define LIB_REVISION    2
  19.  
  20. /*
  21.  * This short assembler section is included here so that
  22.  * there is just one small place where these numbers need to
  23.  * be replaced, instead of in two different files (i.e. here
  24.  * and LibHead.asm).
  25.  */
  26.  
  27. #asm
  28.     PUBLIC    LibVersion
  29.     PUBLIC    LibRevision
  30. LibVersion    EQU    1    ; Shared with libhead via
  31. LibRevision    EQU    2    ; the PUBLIC statement
  32. #endasm
  33.  
  34. /*
  35.  * If the rt_Flags field of the RomTag (struct Resident) has
  36.  * the AUTOINIT bit set, then the rt_Init field must point
  37.  * to a block such the following LibInitBlock.  This block
  38.  * contains four of the five parameters which OpenLibrary()
  39.  * will pass to MakeLibrary.  (The fifth parameter is the
  40.  * SegList.)  If the AUTOINIT bit is not set, then the
  41.  * rt_Init field must point to a routine which will perform
  42.  * the equivalent initialization.
  43.  *
  44.  * When the library is being auto-initialized, a block of
  45.  * memory is allocated by MakeLibrary().  Its size is
  46.  * determined by the length of FunctionList (in Functions.c)
  47.  * and an entry, lib_sizeof_ExtLibrary, in the structure
  48.  * pointed to by rt_Init.  That entry is the size in bytes
  49.  * of the struct ExtLibrary to be allocated automatically,
  50.  * before calling the routine whose address is in
  51.  * lib_InitCode.  So, this value must be known before
  52.  * linking.
  53.  *
  54.  * This can be done by expressing the LibInitBlock structure
  55.  * in C so that the compiler can determine the size for us.
  56.  * This is a drastic improvement over figuring it out by
  57.  * hand!
  58.  */
  59.  
  60. extern long *FunctionList[];
  61. void _LibInitCode();
  62.  
  63. struct {
  64.  
  65.     long lib_sizeof_ExtLibrary; /* Bytes to allocate  */
  66.     APTR lib_FunctionList;        /* Ptr to func list   */
  67.     long lib_InitStruct;        /* see initializers.i */
  68.     APTR lib_InitCode;        /* Ptr to asm routine */
  69.  
  70. } LibInitBlock = {
  71.  
  72.     sizeof( struct ExtLibrary ),
  73.     (APTR) FunctionList,
  74.     0L,                /* No struct init      */
  75.     (APTR) _LibInitCode
  76.  
  77. };
  78.  
  79. /* The assembly routine _LibInitCode calls LibraryInit() to
  80.  * complete the initialization of the library.
  81.  */
  82. struct ExtLibrary *
  83. LibraryInit( LibBasePtr )
  84.  
  85. struct ExtLibrary *LibBasePtr;
  86. {
  87.     /* These initializations are done here because it is
  88.      * difficult to build an initializer structure with
  89.      * Aztec Assembler 3.2.  The argument, the library
  90.      * pointer, is pushed onto the stack by the
  91.      * assembler routine _LibInitCode.
  92.      */
  93.  
  94.     LibBasePtr -> el_Node.ln_Type    = NT_LIBRARY;
  95.     LibBasePtr -> el_Node.ln_Name    = LibraryName;
  96.     LibBasePtr -> el_Version    = LIB_VERSION;
  97.     LibBasePtr -> el_Revision    = LIB_REVISION;
  98.     LibBasePtr -> el_IdString    = (APTR) LibraryId;
  99.  
  100.     /* Now set up the initial values for my libraries'
  101.      * variables.
  102.      */
  103.  
  104.     /* NONE IN THIS EXAMPLE!!! */
  105.  
  106.     return LibBasePtr;    /* This is the value which
  107.                  * will be returned to
  108.                  * MakeLibrary()
  109.                  */
  110. }
  111.  
  112. /*
  113.  * The required routines Open, Close and Expunge are called
  114.  * not by other C routines, but rather by Exec.  This means
  115.  * that their arguments are in registers instead of on the
  116.  * stack.
  117.  *
  118.  * There are three straight forward options at this point:
  119.  *
  120.  *   1)    Use the variable LibraryBase (see LibHead.asm) which
  121.  *    should contain the same value as that in A6.
  122.  *
  123.  *   2)    Immediately call the routine regA6() in LibHead.asm
  124.  *    which will return the value in A6 (Should be the
  125.  *    Library Base Pointer).  This requires that we can be
  126.  *    certain that A6 hasn't been wiped out already by the
  127.  *    compiler generated setup code.
  128.  *
  129.  *   3)    Place an intermediate assembly routine between exec
  130.  *    and each C routine which moves the arguments,
  131.  *    including the Library Base Pointer, from the
  132.  *    registers to the stack.
  133.  *
  134.  * The last method seems the best, so we'll use it.
  135.  */
  136.  
  137. struct ExtLibrary *
  138. Library_Open( LibBasePtr, Version )
  139.  
  140. struct ExtLibrary *LibBasePtr;    /* Was in A6 */
  141. long Version;            /* Was in D0 */
  142. {
  143.     Forbid();
  144.  
  145.     /* Note that another open has occured. */
  146.     LibBasePtr->el_OpenCnt ++;
  147.  
  148.     /* Since we know that there is at least one user of
  149.      * this library, we'll ignore any previous call to
  150.      * Library_Expunge.
  151.      */
  152.      
  153.     LibBasePtr->el_Flags &= ~LIBF_DELEXP;
  154.  
  155.     Permit();
  156.  
  157.     return LibBasePtr;
  158. }
  159.  
  160. /* When the memory allocator in exec.library is looking for
  161.  * more memory, it will try to get rid of the memory used by
  162.  * libraries, devices and fonts.  To do this with a library,
  163.  * it calls Library_Expunge, the third of the required
  164.  * routines.  If Library_Expunge returns zero, then the
  165.  * memory allocator looks elsewhere.  If it returns non-zero
  166.  * then the value must be a pointer to an AmigaDOS SegList.
  167.  * This will be placed on the free list by the memory
  168.  * allocator.  It is the responsibility of the library to
  169.  * free the jump table and Library structure.
  170.  */
  171.  
  172. extern BPTR LibSegList;  /* Allocated in LibHead.asm */
  173.  
  174. BPTR
  175. Library_Expunge( LibBasePtr )
  176.  
  177. struct ExtLibrary * LibBasePtr;    /* Was in A6 */
  178. {
  179.     unsigned long size, JumpTableBase;
  180.  
  181.     /* The memory allocator runs inside a Forbid() /
  182.      * Permit() pair.  To protect against being called
  183.      * by somebody else (i.e. Library_Close).
  184.      */
  185.  
  186.     Forbid ();
  187.  
  188.     if (LibBasePtr->el_OpenCnt > 0) {
  189.         /* Still open, so note the expunge for
  190.          * later use in Library_Close.
  191.          */
  192.         LibBasePtr->el_Flags |= LIBF_DELEXP;
  193.         Permit ();
  194.         return 0;
  195.     }
  196.  
  197.     /* Remove the library from the exec library list
  198.      * so that nobody tries to allocate the library.
  199.      */
  200.  
  201.     Remove( LibBasePtr );
  202.  
  203.     /* Now free up the jump table and library structure.
  204.      * We add the sizes of the two (lib_NegSize is the
  205.      * size of the jump table, and lib_PosSize is the
  206.      * size of struct ExtLibrary), then free the block
  207.      * starting at the base of the jump table.
  208.      */
  209.  
  210.     size = (long)(LibBasePtr->el_NegSize)
  211.          + (long)(LibBasePtr->el_PosSize);
  212.  
  213.     if ( size ) {
  214.         JumpTableBase = (long) LibBasePtr -
  215.             (long) (LibBasePtr->el_NegSize);
  216.  
  217.         FreeMem( JumpTableBase, size );
  218.     }
  219.  
  220.     Permit();
  221.  
  222.     return LibSegList;
  223. }
  224.  
  225. /* When the exec routine CloseLibrary() is called, it calls
  226.  * the required Close() routine of the identified library.
  227.  * That routine is implemented here by Library_Close.  It
  228.  * decrements the open count.  If it is zero, and if the
  229.  * delayed expunge flags is set, then Library_Expunge() is
  230.  * called.  Just as in the case of the Expunge routine, if
  231.  * a non-zero value is returned, it must be a BPTR to an
  232.  * AmigaDOS SegList.
  233.  */
  234.  
  235. BPTR
  236. Library_Close( LibBasePtr )
  237.  
  238. struct ExtLibrary * LibBasePtr;    /* Was in A6 */
  239. {
  240.     Forbid();    /* Have to be cautious when there's
  241.              * not much documentation. */
  242.     LibBasePtr->el_OpenCnt -- ;    /* Decrement */
  243.     Permit();
  244.     
  245.     if (LibBasePtr->el_OpenCnt == 0)
  246.         if ((LibBasePtr->el_Flags & LIBF_DELEXP) != 0)
  247.         return Library_Expunge();
  248.  
  249.     return 0;    /* No expunge. */
  250. }
  251.  
  252. /* Now for the big routine!
  253.  */
  254. long Library_Reserved()
  255. {
  256.     return(0L);
  257. }
  258.